package mmc.server.shell.ops;

import mmc.server.shell.OperationNotAcceptedException;
import mmc.server.shell.Shell;
import mmc.server.shell.ShellException;
import mmc.server.shell.Util;

public class Variable extends Operation implements Assignable{

	protected Object value;
	protected Variable linkedTo = null;
	
    public Variable(String text) throws ShellException {
        super(text = text.trim());
        
        if(!text.matches("[a-zA-z][a-zA-z0-9]*"))
        	throw new OperationNotAcceptedException(false, text + " is not a valid variable name!");
        
        link();
    }

    protected void link(){
    	linkedTo = Shell.environment.get(text);
    }
    
    @Override
    public double execute() {
        return Util.assignToDouble(executeComplex());
    }
    
    @Override
    public void set(Object value){
    	if(linkedTo==null){
    		
    		link();
    		
    		if(linkedTo==null){
	    		Shell.environment.put(text,this);
	    		linkedTo = this;
    		}
    	}
    	
    	linkedTo.value = value;
    }
    
    public Object executeComplex(){
    	if(linkedTo==null){
        	
        	link();
        	
        	if(linkedTo==null)
        		throw new RuntimeException("Variable \""+text+"\" is not set!");
        }
    	
    	return linkedTo.value;
    }
    
    public Class<?> getOutputType(){
    	return linkedTo==null?Object.class:linkedTo.value.getClass();
    }
    
    public static String getDescription(){
    	return formatHelpString("variable","user-defined variable");
    }
    
    public static PriorityType getPriorityType() {
        return PriorityType.VARIABLE;
    }
    
    public static boolean hideInDescription(){
    	return true;
    }
}
